#pragma once

#include "Log.hpp"
#include "Comm.hpp"
#include "User.hpp"
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
using namespace LogMudule;

const std::string gip = "127.0.0.1";
const uint16_t gport = 8000;
const int gsockfd = -1;
class UdpServer
{
private:
    std::string convertToLocalIP(uint32_t networkOrderIP)
    {
        // 将网络字节顺序转换为主机字节顺序
        uint32_t localOrderIP = ntohl(networkOrderIP);

        // 将本地字节顺序的 IP 转换为点分十进制形式
        struct in_addr addr;
        addr.s_addr = localOrderIP;

        // 返回转换后的点分十进制 IP 地址
        return inet_ntoa(addr);
    }
public:
    UdpServer(const uint16_t port = gport)
    :_port(port),_sockfd(gsockfd),_isrunning(false)
    {}
    //初始化服务器
    void Init()
    {
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "Socket creation failed: " << strerror(errno);
        }
        //创建成功
        LOG(LogLevel::INFO) <<"sockfd create success";
        //将本地IP和本地port转化为网络序列
        struct sockaddr_in local;
        local.sin_addr.s_addr = INADDR_ANY;
        local.sin_port = htons(_port);
        local.sin_family = AF_INET;

        //绑定

        int n = bind(_sockfd,(const struct sockaddr*)&local,sizeof(local));
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "bind failed";
            exit(BINDERR);
        }
        //绑定成功
        LOG(LogLevel::INFO) << "bind success";
    }
    //启动服务器
    void Start()
    {
        _isrunning = true;
        char buffer[1024];
        while(true)
        {
            //远端的sockaddr_in
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd,buffer,sizeof(buffer) - 1,0,(struct sockaddr*)&peer,&len);
            //std::cout << "recvfrom： "<< buffer <<  std::endl; 
            if(n > 0)
            {
                buffer[n] = 0;
                uint16_t peerport = ntohs(peer.sin_port);
                std::string peerip = inet_ntoa(peer.sin_addr);
                std::string clientinfo = peerip + ":" + std::to_string(peerport) + " # " + buffer;
                LOG(LogLevel::DEBUG) << clientinfo;
                std::string echo_string = "echo ";
                echo_string += buffer;
                
                //插入到用户表中
                _user_inform.Insert(peerip,peerport);
                for(int i = 0;i < _user_inform.Size();i++)
                {
                    struct sockaddr_in temp;
                    temp.sin_family = AF_INET;
                    //本地点分十进制转换网络字节序
                    temp.sin_addr.s_addr = inet_addr(_user_inform.Ip(i).c_str());
                    temp.sin_port = htons(_user_inform.Port(i));

                    int m = ::sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,(const struct sockaddr*)&temp,sizeof(temp));
                    if(m < 0)
                    {
                        LOG(LogLevel::INFO) << "sendto failed" << strerror(errno);
                        exit(SENDTOERR);
                    }
                    std::cout << i << " ";
                }
                echo_string.clear();
                memset(buffer, '\0', sizeof(buffer));
            }
        }
        _isrunning = false;
    }
    ~UdpServer()
    {
    }
private:
    int _sockfd;
    uint16_t _port;
    bool _isrunning;
    UserManage _user_inform;
};

